/**
 * 月度计划工具类
 *
 * created by wuyp on 2019-05-14 15:10:57.
 */
import Vue from 'vue'
import { isCommonYear, isCommonQuarter, isCommonMonth, computeDateDiff, compareDate } from '@/utils/dateUtils.js'
import asspmgrApi from '@/api/asspmgrApi.js'
import assetbuymgrApi from '@/api/assetbuymgrApi.js'

// 常量accountCode-计划项Code
const ACCOUNT_CODE_KM2001 = 'KM2001' // 提单
const ACCOUNT_CODE_KM2002 = 'KM2002' // 律所进场
const ACCOUNT_CODE_KM2003 = 'KM2003' // 定稿
const ACCOUNT_CODE_KM2004 = 'KM2004' // 过桥
const ACCOUNT_CODE_KM2005 = 'KM2005' // 配售
const ACCOUNT_CODE_KM2006 = 'KM2006' // 缴款
const ACCOUNT_CODE_KM2007 = 'KM2007' // 发行
const ACCOUNT_CODE_KM4001 = 'KM4001' // 提单开始日
const ACCOUNT_CODE_KM4002 = 'KM4002' // 提单结束日
const ACCOUNT_CODE_KM4003 = 'KM4003' // 律所进场开始日
const ACCOUNT_CODE_KM4004 = 'KM4004' // 律所进场结束日
const ACCOUNT_CODE_KM4005 = 'KM4005' // 定稿开始日
const ACCOUNT_CODE_KM4006 = 'KM4006' // 定稿结束日
const ACCOUNT_CODE_KM4007 = 'KM4007' // 过桥开始日
const ACCOUNT_CODE_KM4008 = 'KM4008' // 过桥结束日
const ACCOUNT_CODE_KM4009 = 'KM4009' // 配售开始日
const ACCOUNT_CODE_KM4010 = 'KM4010' // 配售结束日
const ACCOUNT_CODE_KM4011 = 'KM4011' // 缴款开始日
const ACCOUNT_CODE_KM4012 = 'KM4012' // 缴款结束日
const ACCOUNT_CODE_KM4013 = 'KM4013' // 发行开始日
const ACCOUNT_CODE_KM4014 = 'KM4014' // 发行结束日

// 律所进场最小持续天数、最大持续天数
const LAW_FIRM_ENTERING_MIN_KEEP_DAYS = 4
const LAW_FIRM_ENTERING_MAX_KEEP_DAYS = 8

 /**
 * 根据开始日期、结束日期获得月度计划开始和结束时间数组
 * @param {String} startDate 开始日期
 * @param {String} endDate 结束日期
 * @return {Array} 日期数组
 */
export function getDateListByArea (startDate, endDate) {
  let sDate = new Date(startDate)
  let eDate = new Date(endDate)
  const dateList = []
  dateList.push(new Date(startDate))
  while (true) {
    sDate.setDate(sDate.getDate() + 1)
    if (sDate.getTime() < eDate.getTime()) {
      dateList.push(new Date(sDate))
    } else {
      break
    }
  }
  if (Vue.prototype.UtilJs.compareDate(startDate, endDate) < 0) { // 开始日期 != 结束日期
    dateList.push(new Date(endDate))
  }
  return dateList
}

/**
 * 根据accountCode判断是否计划开始项
 * @param {*} accountCode 计划Code
 * @return {boolean} 判断结果
 */
export function isPlanStartItem (accountCode) {
  // 所有属于开始日期的Code
  let startDateCode = [ACCOUNT_CODE_KM4001, ACCOUNT_CODE_KM4003, ACCOUNT_CODE_KM4005, ACCOUNT_CODE_KM4007, ACCOUNT_CODE_KM4009, ACCOUNT_CODE_KM4011, ACCOUNT_CODE_KM4013]
  let item = startDateCode.filter(code => { return code === accountCode })
  return item && item.length > 0
}

/**
 * 根据accountCode判断是否计划结束项
 * @param {*} accountCode 计划Code
 * @return {boolean} 判断结果
 */
export function isPlanEndItem (accountCode) {
  // 所有属于结束日期的Code
  let endDateCode = [ACCOUNT_CODE_KM4002, ACCOUNT_CODE_KM4004, ACCOUNT_CODE_KM4006, ACCOUNT_CODE_KM4008, ACCOUNT_CODE_KM4010, ACCOUNT_CODE_KM4012, ACCOUNT_CODE_KM4014]
  let item = endDateCode.filter(code => { return code === accountCode })
  return item && item.length > 0
}

/**
 * 根据accountCode判断是否是过桥项
 * @param {*} accountCode 计划Code
 * @return {boolean} 判断结果
 */
export function isBridgePlanItem (accountCode) {
  // 过桥项Code
  return accountCode && accountCode === ACCOUNT_CODE_KM2004
}

/**
 * 获取计划项开始日期
 * @param {Object} planItem 计划项
 * @returns {*} 计划项开始日期：null表示未找到
 */
export function getPlanItemSD (planItem) {
  let planSTIndex = planItem.children.findIndex(planElm => { return isPlanStartItem(planElm.accountCode) })
  return (planSTIndex === -1) ? null : planItem.children[planSTIndex].accountValue
}

/**
 * 获取计划项结束日期
 * @param {Object} planItem 计划项
 * @returns {*} 计划项结束日期：null表示未找到
 */
export function getPlanItemED (planItem) {
  let planETIndex = planItem.children.findIndex(planElm => { return isPlanEndItem(planElm.accountCode) })
  return (planETIndex === -1) ? null : planItem.children[planETIndex].accountValue
}

/**
 * 根据计划项Code获取计划项的定义顺序
 * @param {Number} accountCode 计划项Code
 * @return {Number} 计划项的定义顺序
 */
export function getPlanItemDefineOrderByCode (accountCode) {
  var defOrder = -1 // -1表示没有该项
  switch (accountCode) {
    case ACCOUNT_CODE_KM2001 : { defOrder = 1; break }
    case ACCOUNT_CODE_KM2002 : { defOrder = 2; break }
    case ACCOUNT_CODE_KM2003 : { defOrder = 3; break }
    case ACCOUNT_CODE_KM2004 : { defOrder = 3; break }
    case ACCOUNT_CODE_KM2005 : { defOrder = 4; break }
    case ACCOUNT_CODE_KM2006 : { defOrder = 5; break }
    case ACCOUNT_CODE_KM2007 : { defOrder = 6; break }
    default: break
  }
  return defOrder
}

/**
 * 获取正确的计划项顺序提示消息
 * @param {String} accountCode 计划项Code
 * @return {String} 正确的计划项顺序提示消息
 */
export function getTrueOrderMsg (accountCode) {
  var msg = ''
  switch (accountCode) {
    case ACCOUNT_CODE_KM2001 : { msg = '提单应不晚于除了提单的所有计划项!'; break }
    case ACCOUNT_CODE_KM2002 : { msg = '律所进场应不早于提单，不晚于定稿或过桥,且应在提单开始后2~4天开始!'; break }
    case ACCOUNT_CODE_KM2003 : { msg = '定稿应不早于提单、律所进场，不晚于配售![提单<律所进场<定稿<配售<缴款<=发行]!'; break }
    case ACCOUNT_CODE_KM2004 : { msg = '过桥应不早于提单、律所进场，不晚于缴款和发行[提单<律所进场<过桥<=缴款<=发行]!'; break }
    case ACCOUNT_CODE_KM2005 : { msg = '配售应不早于提单、律所进场、定稿，不晚于缴款和发行[提单<律所进场<定稿<配售<缴款<=发行]!'; break }
    case ACCOUNT_CODE_KM2006 : { msg = '缴款应不早于提单、律所进场、过桥、定稿、配售，不晚于发行!'; break }
    case ACCOUNT_CODE_KM2007 : { msg = '发行应不早于任何计划项!'; break }
    default: break
  }
  return msg
}

/**
 * 获取发行计划项accountCode
 * @returns {String} 发行计划项accountCode
 */
export function getReleasePlanAccountCode () {
  // 发行的accountCode
  return ACCOUNT_CODE_KM2007
}

/**
 * 是否需要进行计划项持续天数的检测
 *  --> 目前只有律所进场需要进行检查
 * @param {String} accountCode 计划项Code
 * @returns {Boolean} 判断结果：true是，false否
 */
export function isNeedCheckKeeyDays (accountCode) {
  // 律所进场Code
  return !Vue.prototype.UtilJs.isEmpty(accountCode) && accountCode === ACCOUNT_CODE_KM2002
}

/**
 * 根据accountCode获取计划项约束-保持天数
 * @param {String} accountCode 计划项Code
 * @returns {Object} 计划项保持天数约束
 */
export function getConstraintKeepDays (accountCode) {
  var result = {
    minKeepDays: 0,
    maxKeepDays: 9999
  }
  // 律所进场：应持续4-8日
  if (accountCode === ACCOUNT_CODE_KM2002) {
    result.minKeepDays = LAW_FIRM_ENTERING_MIN_KEEP_DAYS
    result.maxKeepDays = LAW_FIRM_ENTERING_MAX_KEEP_DAYS
  }
  return result
}

/**
 * 根据specialPlanId获取专项计划信息
 * @param {String} specialPlanId 专项计划Id
 * @returns {Object} 专项计划
 */
export async function getSpecPlanBasicById (specialPlanId) {
  if (!Vue.prototype.UtilJs.isEmpty(specialPlanId)) {
    var specialPlanBasic = await asspmgrApi.specialPlanBasicInfo.getList({specialPlanId: specialPlanId}).then(res => {
      return (!Vue.prototype.UtilJs.isEmpty(res.data) && res.data.length > 0) ? res.data[0] : specialPlanBasic
    })
  }
  return specialPlanBasic
}

/**
 * 获取专项计划分档分批放款计划信息
 * @Get /api/asspmgr/specfilloan/list
 * @param {String} specialPlanId 专项计划ID
 * @returns {Array} 专项计划分档分批放款计划信息列表
 */
export async function getSpecPlanFillLoanList (specialPlanId) {
  var res = await asspmgrApi.specialPlanSpecfilloan.getList({ specialPlanId: specialPlanId }).then(response => {
    return response.data
  })
  return res
}

/**
 * 获取ABS过桥机构额度基本信息
 * @Get/api/assetbuymgr/bridcroquot/ids
 * @param {Array} ids 过桥额度Id数组
 * @returns {*} 过桥额度信息
 */
export async function getSpecPlanBridQuot (ids) {
  var res = await assetbuymgrApi.bridcroquot.getList({ids: ids}).then(resp => {
    // return (!Vue.prototype.UtilJs.isEmpty(resp.data) && resp.data.length > 0) ? resp.data : null
    return resp.data
  })
  return res
}

/**
 * 获取过桥可用额度（当前过桥日的可用额度）
 * 逻辑梳理：
 *  1.[核心企业]: 遍历bridAmountInfoList，与bridAmountInfoList.bridAmountInfoList({[]})中的coreEnterpriseId、bridcroquotId比较（同一过桥机构、同一核心企业）
 *  2.[项目ID]: 若bridAmountInfo.projectId !== '' ，则根据 projectId 筛选 bridAmountInfoList（bridAmountInfo.projectId === projectId）
 *  3.[托管行]:
 *      3.1 若bridAmountInfo.bundledCustodyStatus === '1',则根据specialPlanId获取托管行（一个专项id只能拿到一个托管行id）
 *      3.2 筛选bridAmountInfo.bridcrossinsId属于专项计划的托管行的那些bridAmountInfoList项
 *  4.[时间跨度]: 根据 bridDate、releaseDate、是否跨月、跨季、跨年筛选满足条件的bridAmountInfoList项
 *  5.[过桥使用时间]: 根据 bridDate、releaseDate、最小占用时间、最大占用时间筛选，bridAmountInfo.minimumOccupyTime <= releaseDate - bridDate <= bridAmountInfo.maximumOccupyTime
 *  6.[额度生效时间]: 筛选 额度实际生效时间bridAmountInfo.actualEffectiveTime  <= 过桥日 <= 额度失效时间bridAmountInfo.failureTime 的bridAmountInfoList项
 *  7.[可用额度计算]:
 *      7.1 build过桥机构分组信息：根据过桥机构Id对bridAmountInfoList分组，临时额度的过桥机构单独算一家（bridAmountInfo.provisionalQuotaStatus === 是临时额度的字典项值）
 *      7.2 对每家过桥机构进行以下计算：
 *           7.2.1 获取当前过桥机构额度列表中批复额度最大的一项 maxItem
 *           7.2.2 可用额度canUseAmount = maxItem.批复额度approvalLimit
 *           7.2.3 预占额度planOccupyAmount = maxItem.预占额度estimateOccupyQuota
 *           7.2.4 canUseAmount = canUseAmount - Sum(已占额度usedQuota) - 预占额度planOccupyAmount)
 *  8.[返回值构造]：
 *      birdCanUseAmountInfo = [
 *         {
 *            bridcrossinsId  // 过桥机构Id
 *            bridcrossinsCode  // 过桥机构Code = 过桥机构Id_是否临时额度
 *            bridcrossinsId  // 过桥机构名称
 *            canUseAmount    // 可用额度
 *         },
 *         {}...
 *      ]
 *   20190531变更-->返回值结构 birdCanUseAmountInfo= [
 *         {
 *            ...curBridAmountInfo, // 当前过桥机构信息（来自bridAmountInfoList）
 *            bridcrossinsCode // 过桥机构Code = 过桥机构Id_是否临时额度
 *            canUseAmount     // 可用额度
 *         },
 *         {}
 *     ]
 * @param {String} coreEnterpriseId 核心企业ID[非空]
 * @param {String} projectId 项目ID[非空]
 * @param {String} custodianBankId 托管行ID
 * @param {*} bridDate 过桥日[非空]
 * @param {*} releaseDate 发行日
 * @param {Array} bridAmountInfoList 过桥额度信息列表
 * @returns {*} 过桥可用额度信息列表
 */
export function getBridgeCanUseAmout (coreEnterpriseId, projectId, custodianBankId, bridDate, releaseDate, bridAmountInfoList) {
  // 参数判断
  if (Vue.prototype.UtilJs.isEmpty(coreEnterpriseId) || Vue.prototype.UtilJs.isEmpty(projectId) || Vue.prototype.UtilJs.isEmpty(bridDate) ||
      Vue.prototype.UtilJs.isEmpty(bridAmountInfoList) || bridAmountInfoList.length <= 0) {
    return []
  }
  var bridCrossInsCanUseAmount = []

  // 一、筛选满足条件的过桥额度信息列表
  var bridAmountFliteredList = bridAmountInfoList.filter(bridAmountInfo => {
    var flag = true
    // 1.[核心企业]
    if (!Vue.prototype.UtilJs.isEmpty(bridAmountInfo.bridcroquotAndCoreEnterprises) && bridAmountInfo.bridcroquotAndCoreEnterprises.length > 0) {
      let bridCoreEnterpIndex = bridAmountInfo.bridcroquotAndCoreEnterprises.findIndex(bridCoreEnterp => {
        return bridCoreEnterp.bridcroquotId === bridAmountInfo.keyId && bridCoreEnterp.coreEnterpriseId === coreEnterpriseId
      })
      flag = flag && (bridCoreEnterpIndex !== -1)
    }

    // 2.[项目ID]
    if (flag) {
      flag = flag && (bridAmountInfo.projectId === projectId)
    }

    // 3.[托管行]
    if (flag && bridAmountInfo.bundledCustodyStatus === '1') {
      flag = flag && !Vue.prototype.UtilJs.isEmpty(custodianBankId) && bridAmountInfo.bridcrossinsId === custodianBankId
    }

    // 4.[时间跨度]
    if (flag && bridAmountInfo.canExtendYear === '0' && !Vue.prototype.isEmpty(releaseDate)) { // 不能跨年
      flag = flag && isCommonYear(bridDate, releaseDate)
    }
    if (flag && bridAmountInfo.canExtendQuarter === '0' && !Vue.prototype.isEmpty(releaseDate)) { // 不能跨季
      flag = flag && isCommonQuarter(bridDate, releaseDate)
    }
    if (flag && bridAmountInfo.canExtendMonth === '0' && !Vue.prototype.isEmpty(releaseDate)) { // 不能跨月
      flag = flag && isCommonMonth(bridDate, releaseDate)
    }

    // 5.[过桥使用时间]
    if (flag && !Vue.prototype.UtilJs.isEmpty(bridAmountInfo.minimumOccupyTime) && !Vue.prototype.UtilJs.isEmpty(bridAmountInfo.maximumOccupyTime) &&
      !isNaN(parseInt(bridAmountInfo.minimumOccupyTime)) && !isNaN(parseInt(bridAmountInfo.maximumOccupyTime)) &&
      parseInt(bridAmountInfo.minimumOccupyTime) > 0 && parseInt(bridAmountInfo.maximumOccupyTime) > 0 && !Vue.prototype.isEmpty(releaseDate)) {
      // 此处computeDateDiff()计算结果需要再+1，因计算的是间隔时间，需再加上过桥的那天（不算发行那天）
      flag = flag && parseInt(bridAmountInfo.minimumOccupyTime) <= computeDateDiff(releaseDate, bridDate) + 1 && computeDateDiff(releaseDate, bridDate) + 1 <= parseInt(bridAmountInfo.maximumOccupyTime)
    }

    // 6.[额度生效时间]：bridAmountInfo.actualEffectiveTime <= bridDate <= bridAmountInfo.failureTime
    if (flag && !Vue.prototype.UtilJs.isEmpty(bridAmountInfo.actualEffectiveTime) && !Vue.prototype.UtilJs.isEmpty(bridAmountInfo.failureTime)) {
      flag = flag && (compareDate(bridAmountInfo.actualEffectiveTime, bridDate) <= 0 && compareDate(bridDate, bridAmountInfo.failureTime) >= 0)
    }

    return flag
  })

  // 二、对筛选后的bridAmountInfoList按过桥机构分组
  var bridAmountGroupedList = bridAmountListGroupByCrossIns(bridAmountFliteredList)

  // 三、计算过桥机构可用额度
  bridAmountGroupedList.forEach(bridInsAmountInfo => {
    // 获取列表中批复额度最大的一项、计算已占额度总和
    var maxItemIndex = 0
    var usedQuotaTotal = 0
    for (var i = 0; i < bridInsAmountInfo.data.length; i++) {
      usedQuotaTotal += parseInt(bridInsAmountInfo.data[i].usedQuota)
      if (parseInt(bridInsAmountInfo.data[maxItemIndex].approvalLimit) < parseInt(bridInsAmountInfo.data[i].approvalLimit)) {
        maxItemIndex = i
      }
    }
    var maxItem = bridInsAmountInfo.data[maxItemIndex]
    // 可用额度
    var canUseAmount = parseInt(maxItem.approvalLimit)
    // 预占额度
    var planOccupyAmount = parseInt(maxItem.estimateOccupyQuota)
    // 可用额度 = 最大批复额度 - 已占额度总和 - 最大批复额度的过桥机构额度基本信息项.预占额度
    canUseAmount = canUseAmount - usedQuotaTotal - planOccupyAmount

    // 四、构造返回值
    // var resItem = {
    //   bridcrossinsId: bridInsAmountInfo.bridcrossinsId,
    //   bridcrossinsCode: bridInsAmountInfo.bridcrossinsCode,
    //   bridcrossinsName: bridInsAmountInfo.bridcrossinsName,
    //   canUseAmount: canUseAmount
    // }
    var resItem = { ...maxItem, ...{bridcrossinsCode: bridInsAmountInfo.bridcrossinsCode, canUseAmount: canUseAmount} }
    bridCrossInsCanUseAmount.push(resItem)
  })

  return bridCrossInsCanUseAmount
}

/**
 * 过桥机构额度列表按过桥机构分组
 * @param {Array} bridAmountList 过桥机构额度列表
 * @returns {Array} 分组结果 [{bridcrossinsId:'', bridcrossinsCode: '', bridcrossinsName: '', data: [过桥机构额度数组]},{}...]
 */
export function bridAmountListGroupByCrossIns (bridAmountList) {
  var amountInfo = {}
  var groupRes = []
  bridAmountList.forEach(item => {
    let itemCode = item.bridcrossinsId + '_' + item.provisionalQuotaStatus
    if (!amountInfo[item.bridcrossinsId] || (amountInfo[item.bridcrossinsId] && !amountInfo[itemCode])) {
      // 新增过桥机构分组
      groupRes.push({
        bridcrossinsId: item.bridcrossinsId,
        bridcrossinsCode: itemCode,
        bridcrossinsName: item.bridcrossinsName,
        data: [item]
      })
      amountInfo[item.bridcrossinsId] = item.bridcrossinsId
      amountInfo[itemCode] = itemCode
    } else {
      // 过桥机构已有，合并处理
      for (var i = 0; i < groupRes.length; i++) {
        if (groupRes[i].bridcrossinsCode === itemCode) {
          groupRes[i].data.push(item)
          break
        }
      }
    }
  })
  return groupRes
}
